#include "AEEListForm.h"
#include "AEEListWidget.h"
#include "AEEStaticWidget.h"
#include "screen_layout.h"
#include "dfon_comdef.h"

#include "fsmodel.h"
#include "textitem.h"
#include "thumbitem.h"
#include "fullscritem.h"
#include "catinfo.h"
#include "catform.h"
#include "mgallery.h"
#include "kmglang_en.h"
#include "skops.h"
#include "actionops.h"
#include "dfon_shared_if_voice_memo.h"

typedef struct
{
	MGallery *me;
	ModelListener viewModelListener;
	ModelListener fsModelListener;
	HandlerDesc hdesc;
	IListModel *listModel;
	CatInfo catInfo;
	IForm *form;
	uint16 *sks;
	int skCount;
	IPTLayer_SoftkeyWin *skWin;
	NodeGeneric *focusedNode;
	boolean listLoaded;
} FormData ;

static void CreateFullScreenForm(MGallery *me, FormData *oldFormData);

static void FormSKProxy(FormData *formData, int id)
{
	//check for specific options like IDS_VIEW, all other will handle skops
	if(id == IDS_VIEW && formData->catInfo.viewType == ViewTypeThumbnail)
	{
		CreateFullScreenForm(formData->me, formData);
	}
	SKOps_HandleSK(formData->me, (IVectorModel*)formData->listModel, 
		&formData->catInfo, formData->focusedNode, (uint16)id);
}

static void FormUpdateSk(FormData *formData)
{
	MGallery *me = formData->me;
	if(formData->sks)
	{
		if(formData->skCount > 2)
			IPTLAYER_FormSetSoftKeys(me->ptl, me->rf, formData->form, me->resFileName, formData->sks[0], IDS_OPTIONS);
		else if(formData->skCount == 2)
			IPTLAYER_FormSetSoftKeys(me->ptl, me->rf, formData->form, me->resFileName, formData->sks[0], formData->sks[1]);
		else if(formData->skCount == 1)
			IPTLAYER_FormSetSoftKeys(me->ptl, me->rf, formData->form, me->resFileName, formData->sks[0], 0);
		else if(formData->skCount == 0)
			IPTLAYER_FormSetSoftKeys(me->ptl, me->rf, formData->form, me->resFileName, 0, 0);
	}
	else
	{
		IPTLAYER_FormSetSoftKeys(me->ptl, me->rf, formData->form, me->resFileName, 0, 0);
	}
}

static void ScheduleLoadImages(void *data)
{
	FormData *formData = data;
	IWidget *list = NULL;
	int cols = 0, rows = 0, topIndex = 0;

	if(formData->catInfo.viewType != ViewTypeThumbnail)
		return;

	IFORM_GetWidget(formData->form, WID_LIST, &list);

	IWIDGET_GetTopIndex(list, &topIndex);
	IWIDGET_GetCols(list, &cols);
	IWIDGET_GetRows(list, &rows);
	
	IFSMODEL_LoadImages((IFSModel*)formData->listModel, topIndex, rows*cols);

	RELEASEIF(list);
}

static void RecordVMCallback(void *data, int lsk)
{
	MGallery *me = data;
	if(lsk == IDS_YES)
	{
		UTIL_HISTORY_DATA histData;
		ZEROAT(&histData);
		histData.sender = AEECLSID_MG;
		histData.target = AEECLSID_DIFFON_VOICEMEMO;
		histData.IFSymbol = DFON_VOICEMEMO_IF_TYPE_MYSTUFF_RECORD_TERMINATE;
		DFON_IUTILLIB_SetHistory(me->utils, DFON_HISTORY_VOICEMEMO, &histData);
		ISHELL_StartApplet(me->shell, AEECLSID_DIFFON_VOICEMEMO);
	}
}

static void FormModelListener(void *data, ModelEvent *event)
{
	FormData *formData = data;
	MGallery *me = formData->me;
	NodeGeneric *node = NULL;
	ILISTMODEL_GetAt(formData->listModel, event->dwParam, (void**)&node);

	if(event->evCode == EVT_MDL_FOCUS_SELECT && node && node->type == NodeTypeAction){
			NodeAction *nodeAction = (NodeAction*)node;
			if(CatInfo_GetInfo(nodeAction->id, NULL))
				CatForm_Create(me, nodeAction->id);
			else
				ActionOps_HandleAction(me, &formData->catInfo, nodeAction);
	}
	else if(event->evCode == EVT_MDL_FOCUS_CHANGE){		
		//save selected node
		formData->focusedNode = node;

		//start playing if category autoplayable
		if(formData->catInfo.autoPlay){
			DFON_ISOUNDLIB_SoundStop(me->sndLib);
			if(node && node->type == NodeTypeFile){
				NodeFile *nodeFile = (NodeFile*)node;
				DFON_ISOUNDLIB_SoundPlayFile(me->sndLib, nodeFile->fi.szName, 1);
			}
		}

		//regenerate sks
		FREEIF(formData->sks);
		formData->skCount = 0;
		SKOps_GetList(&formData->catInfo, node, me->mode, &formData->sks, &formData->skCount);
		FormUpdateSk(formData);
	}else if(event->evCode == EVT_MDL_LOADED){
		formData->listLoaded = TRUE;
		if(ILISTMODEL_Size(formData->listModel) == 0){
			if(formData->catInfo.catID == IDS_VOICEMEMOS){
				AlertDesc alert = {NULL, IDS_QUESTION, IDS_RECORD_NEW_VMU, 0};
				alert.resName = me->resFileName;
				alert.icon = IPTLAYER_ALERTWIN_ICONQUESTION;
				alert.lsk = IDS_YES;
				alert.rsk = IDS_NO;
				alert.timeout = -1;
				IPTLAYER_MakeAlert(me->ptl, &alert, RecordVMCallback, me);
			}else{
				AlertDesc alert = {NULL, IDS_ATTENTION, IDS_NOFILES_SAVED, 0};
				alert.resName = me->resFileName;
				alert.icon = IPTLAYER_ALERTWIN_ICONATTENTION;
				IPTLAYER_MakeAlert(me->ptl, &alert, NULL, NULL);
			}
			IFORM_HandleEvent(formData->form, EVT_FORM_CANCEL, 0, 0);
		}else{
			ScheduleLoadImages(formData);
		}
	}else if(event->evCode == EVT_MDL_SCROLL_CHANGE && formData->listLoaded && formData->catInfo.viewType == ViewTypeThumbnail){
		ScheduleLoadImages(formData);
	}
}

static void FormFree(void *data)
{
	FormData *formData = data;

	LISTENER_Cancel(&formData->viewModelListener);
	LISTENER_Cancel(&formData->fsModelListener);
	FREEIF(formData->sks);
	if(formData->me->ptl && formData->skWin)
		IPTLAYER_SoftkeyWinDestroy(formData->me->ptl, formData->skWin);

	HANDLERDESC_Free(&formData->hdesc);
	FREEIF(formData);
}

static void SKWinCloseHandler(void *data, int id)
{
	FormData *formData = data;
	if(id > 0 || id == PTLAYER_MENULIST_CLR || id == PTLAYER_MENULIST_SOFT2)
		IPTLAYER_SoftkeyWinShow(formData->me->ptl, formData->skWin, FALSE);
	if(id > 0)
		FormSKProxy(formData, id);
}

static boolean FormHandleEvent(void *data, AEEEvent evt, uint16 wParam, uint32 dwParam)
{
	FormData *formData = data;
	MGallery *me = formData->me;

	if(evt == EVT_WDG_SETPROPERTY)
	{
		switch (wParam)
		{
		case FID_ACTIVE:
			if(dwParam == TRUE)
			{
				IWidget *list = NULL;
				IPTLAYER_FormSetTitle(me->ptl, me->rf, formData->form, me->resFileName, formData->catInfo.catID);
				IFORM_GetWidget(formData->form, WID_LIST, &list);
				if(formData->catInfo.viewType == ViewTypeThumbnail || formData->catInfo.viewType == ViewTypeFullscr){
					IWIDGET_Animate(list, TRUE);
				}else{
					IWIDGET_SetItemHeight(list, KWC_MENU_ITEM_HEIGHT);
				}
				RELEASEIF(list);
				FormUpdateSk(formData);
			}
			else
			{
				IWidget *list = NULL;
				DFON_ISOUNDLIB_SoundStop(me->sndLib);
				IFORM_GetWidget(formData->form, WID_LIST, &list);
				IWIDGET_Animate(list, FALSE);
				RELEASEIF(list)
			}
			break;
		}
	}

	if(evt == EVT_KEY && (wParam == AVK_SOFT1 || wParam == AVK_SOFT2) && formData->skCount){
		if(formData->skCount > 2 && wParam == AVK_SOFT2){
			int i = 0;
			if(formData->skWin != NULL)
				IPTLAYER_SoftkeyWinDestroy(me->ptl, formData->skWin);
			IPTLAYER_SoftkeyWinCreateEx(me->ptl, &formData->skWin, SKWinCloseHandler, formData);
			for(i = 1; i<formData->skCount; i++)
				IPTLAYER_SoftkeyWinSetItem(me->ptl, formData->skWin, formData->sks[i], me->resFileName, formData->sks[i]);
			IPTLAYER_SoftkeyWinShow(me->ptl, formData->skWin, TRUE);
		}else if(formData->skCount == 2 && wParam == AVK_SOFT2){
			FormSKProxy(formData, formData->sks[1]);
		}else if(formData->skCount >= 1 && wParam == AVK_SOFT1){
			FormSKProxy(formData, formData->sks[0]);
		}
		return TRUE;
	}

	return HANDLERDESC_Call(&formData->hdesc, evt, wParam, dwParam);
}


static void CreateFullScreenForm(MGallery *me, FormData *oldFormData)
{
	IForm *mainForm = NULL;
	FormData *formData = MALLOCREC(FormData);
	IWidget *item = NULL;
	IWidget *list = NULL;
	IModel *viewModel = NULL;
	int focusIndex;
	
	FullscrItem_New(&item, me->shell);
	ISHELL_CreateInstance(me->shell, AEECLSID_LISTFORM, (void**)&mainForm);
	ISHELL_CreateInstance(me->shell, AEECLSID_PICKWIDGET, (void**)&list);
	
	IFORM_SetWidget(mainForm, WID_LIST, list);
	IFORM_SetWidget(mainForm, WID_FORM, list);

	//some props to form
	HANDLERDESC_Init(&formData->hdesc, FormHandleEvent, formData, FormFree);
	IFORM_SetWidget(mainForm, WID_LISTITEM, item);
	IFORM_SetProperty(mainForm, FID_LISTMODEL, (uint32)oldFormData->listModel);
	IFORM_SetHandler(mainForm, &formData->hdesc);
	IWIDGET_SetProperty(item, PROP_LEFT_ARROW, (uint32)me->leftArrow);
	IWIDGET_SetProperty(item, PROP_RIGHT_ARROW, (uint32)me->rightArrow);
	
	//add listener to list view model
	IWIDGET_GetViewModel(list, &viewModel);
	if(viewModel)
	{
		IMODEL_AddListenerEx((IModel*)viewModel, &formData->viewModelListener, FormModelListener, formData);
		RELEASEIF(viewModel);
	}
	
	//init formData
	formData->me = me;
	formData->listModel = (IListModel*)oldFormData->listModel;
	formData->catInfo = oldFormData->catInfo;
	formData->catInfo.viewType = ViewTypeFullscr;
	formData->form = mainForm;
	
	//push to rootform	
	IFORM_SetThemeBaseName(mainForm, "MGFullscr");
	IROOTFORM_PushForm(me->rf, mainForm);
	IWIDGET_SetCols(list, 1);

	//restore to old index
	IFORM_GetProperty(oldFormData->form, FID_LISTINDEX, (uint32)&focusIndex);
	IFORM_SetProperty(mainForm, FID_LISTINDEX, focusIndex);
	
	RELEASEIF(list);
	RELEASEIF(item);
}

boolean CatForm_Create(MGallery *me, uint16 catID)
{
	boolean retval = FALSE;
	IForm *mainForm = NULL;
	IFSModel *model = NULL;
	IModel *viewModel = NULL;
	IWidget *item = NULL;
	IWidget *list = NULL;
	CatInfo catInfo = {0};
	FormData *formData = MALLOCREC(FormData);

	CatInfo_GetInfo(catID, &catInfo);

	//create needed objects
	ISHELL_CreateInstance(me->shell, AEECLSID_LISTFORM, (void**)&mainForm);
	FSModel_New(&model, me->shell, NULL);
	if(catInfo.viewType == ViewTypeThumbnail)
		ThumbItem_New(&item, me->shell);
	else
		TextItem_New(&item, me->shell);

	if(!me->rf || !mainForm || !item || !model || !formData)
		goto cleanup;

	//if thumbnails replace listwidget with gridwidget
	if(catInfo.viewType == ViewTypeThumbnail)
	{
		IWidget *gridWidget = NULL;
		ISHELL_CreateInstance(me->shell, AEECLSID_GRIDWIDGET, (void**)&gridWidget);
		if(!gridWidget)
			goto cleanup;
		IFORM_SetWidget(mainForm, WID_LIST, gridWidget);
		IFORM_SetWidget(mainForm, WID_FORM, gridWidget);
		RELEASEIF(gridWidget);
	}

	//init fsmodel
	IFSMODEL_SetActionList(model, catInfo.actionList, me->resFileName);
	IFSMODEL_SetPathList(model, catInfo.pathList);
	IMODEL_AddListenerEx((IModel*)model, &formData->fsModelListener, FormModelListener, formData);

	//set numberimages array to textitem
	if(catInfo.viewType == ViewTypeNumberedList)
	{
		IWIDGET_SetProperty(item, PROP_NUMBERED_IMAGES_VECTOR, (uint32)me->numberImages);
	}

	//some props to form
	HANDLERDESC_Init(&formData->hdesc, FormHandleEvent, formData, FormFree);
	IFORM_SetProperty(mainForm, FID_LISTMODEL, (uint32)model);
	IFORM_SetWidget(mainForm, WID_LISTITEM, item);
	IFORM_SetHandler(mainForm, &formData->hdesc);

	//add listener to list view model
	IFORM_GetWidget(mainForm, WID_LIST, &list);
	IWIDGET_GetViewModel(list, &viewModel);
	if(viewModel)
	{
		IMODEL_AddListenerEx((IModel*)viewModel, &formData->viewModelListener, FormModelListener, formData);
		RELEASEIF(viewModel);
	}

	//init formData
	formData->me = me;
	formData->listModel = (IListModel*)model;
	formData->catInfo = catInfo;
	formData->form = mainForm;

	//push to rootform	
	if(catInfo.viewType == ViewTypeThumbnail)
		IFORM_SetThemeBaseName(mainForm, "MGThumbnails");
	else
		IFORM_SetThemeBaseName(mainForm, "MGList");
	IROOTFORM_PushForm(me->rf, mainForm);

	if(catInfo.viewType == ViewTypeThumbnail)
	{
		IWIDGET_SetCols(list, 3);
		IWIDGET_SetRows(list, 3);
	}
	else
	{
		IPTLAYER_AddIndexerForList(me->ptl, list, LIST_TYPE_ONE_LINE);
	}

	retval = TRUE;

cleanup:
	if(!retval)
		FREEIF(formData);
	RELEASEIF(list);
	RELEASEIF(item);
	RELEASEIF(model);
	RELEASEIF(mainForm);

	return retval;
}
